import json
from time import sleep, time

import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from urllib import request
from selenium.webdriver.support.wait import WebDriverWait
from constant import CHROME_DRIVER_PATH, LOGIN_URL, PHONE_CODE_INVALID_TIME, SENDING, INVALID, WORK_URL, JINGDONG
from cvImage import CvImageDistance
import math
import random
from inits import dbSession, logger
from phone import http_phone
from tables.his_kpi import his_kpi
from tables.shop_report import shop_report
from tables.sk_shop_info import sk_shop_info
from tables.sk_shop_phone_code import sk_shop_phone_code
import pyautogui
import datetime

class web_drivers():

    def __init__(self, shop, accounts):
        # 店铺信息
        self.shop = shop
        # 账号信息
        self.accounts = accounts

        # 设置参数
        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
        chrome_options.add_experimental_option('useAutomationExtension', False)
        # chrome_options.add_argument('lang=zh-CN,zh,zh-TW,en-US,en')
        chrome_options.add_argument('--incognito')  # 打开隐身窗口
        # chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36')
        chrome_options.add_argument("--disable-blink-features=AutomationControlled")
        browser = webdriver.Chrome(executable_path=CHROME_DRIVER_PATH, options=chrome_options)
        # web driver
        self.browser = browser

    def process(self, timestamp):
        try:
            # 账号登录
            self.login()

            # 等待页面加载
            sleep(2)
            shop = sk_shop_info()
            shop.update_shop_abnormal(shop_id=self.shop[0])

            # 滑块拖动
            slick = False
            slider_retry = 0  # 重试5次
            while slick is False and slider_retry < 8:
                slider_retry += 1
                slick = self.slider()
                sleep(2)
            if slick is False:
                return self.shop

            # 手机验证码
            sleep(1.5)
            phoneCode = self.commit_phone_code()
            if phoneCode is False:
                return self.shop

            # 三秒跳转
            sleep(3)

            # 获取数据
            cookies = ""
            all_cookies = self.browser.get_cookies()
            for cookie in all_cookies:
                cookies += cookie['name'] + "=" + cookie['value'] + "; "

            # 获取工作量数据
            data = self.get_url_his_data(timestamp=timestamp, cookie=cookies)
            hisKpi = his_kpi()
            if len(data) > 0:
                hisKpi.batch_save_his_data(his_data=data)

            # 昨日的数据
            yesterday = timestamp - 86400
            yesterData = self.get_url_his_data(timestamp=yesterday, cookie=cookies)
            if len(yesterData) > 0:
                hisKpi.batch_save_his_data(his_data=yesterData)

            threeDay = timestamp - (86400 * 2)
            threeData = self.get_url_his_data(timestamp=threeDay, cookie=cookies)
            if len(threeData) > 0:
                hisKpi.batch_save_his_data(his_data=threeData)

        except Exception:
            return self.shop
        finally:
            self.browser.close()
            self.browser.quit()

    # 登录
    def login(self):

        # 读取JS文件
        f = open("stealth.min.js", mode="r", encoding="utf-8").read()
        self.browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            "source": f
        })

        # 隐式页面加载10秒
        self.browser.implicitly_wait(10)
        # 打开登录页面
        self.browser.get(LOGIN_URL)

        # 最大化窗口
        self.browser.maximize_window()

        sleep(2)
        # 填写账号密码
        self.browser.find_element(By.ID, "loginname").send_keys(self.shop[5])
        self.browser.find_element(By.ID, "nloginpwd").send_keys(self.shop[6])

        # 点击登录
        self.browser.find_element(By.CLASS_NAME, "login-btn").click()

    def slider_distance(self):
        # 拖动的滑块小图
        small_div = self.browser.find_element(By.CLASS_NAME, "JDJRV-smallimg")
        tag_img = small_div.find_element(By.TAG_NAME, "img").get_attribute("src")

        # 背景大图
        big_div = self.browser.find_element(By.CLASS_NAME, "JDJRV-bigimg")
        background_img = big_div.find_element(By.TAG_NAME, "img").get_attribute("src")

        # 存入图片
        request.urlretrieve(background_img, "background.png")
        request.urlretrieve(tag_img, "tag.png")

        cvObj = CvImageDistance()

        distance = cvObj.get_distance(background_img_path="background.png", tag_img_path="tag.png")
        return distance

    # 滑块拖动
    def slider(self):
        # 滑块弹窗
        slider = self.browser.find_elements(By.CLASS_NAME, "JDJRV-click-bind-suspend")
        if len(slider) > 0:

            distance = self.slider_distance()
            while distance <= 60 or distance >= 210:
                self.browser.find_element(By.CLASS_NAME, "JDJRV-img-refresh").click()
                sleep(2)
                distance = self.slider_distance()

            # 拖动的滑块小图
            small_div = self.browser.find_element(By.CLASS_NAME, "JDJRV-smallimg")
            tag_path = small_div.find_element(By.XPATH, "img")
            # 网页元素到pyautogui有比例缩放 (本机电脑的比例)
            tagx = tag_path.location.get("x")
            tagy = tag_path.location.get("y") * 1.30

            # 移动到滑块位子
            pyautogui.moveTo(tagx, tagy, duration=0.5)
            # 点下鼠标
            pyautogui.mouseDown()

            rangeDistance = random.randint(10, 15)
            moveDistance = distance-rangeDistance
            pyautogui.moveTo(tagx+moveDistance, tagy-2, duration=1.545)
            pyautogui.moveTo(tagx+distance, tagy+2, duration=0.063)
            sleep(0.283)
            pyautogui.moveTo(tagx+distance+2, tagy+1, duration=0.201)
            sleep(0.586)
            pyautogui.moveTo(tagx+distance+1, tagy+1, duration=0.389)

            pyautogui.mouseUp()

            # range_list = self.range_ragulation(distance=distance)
            # # 移动距离
            # rangeTimeList = [0.023, 0.033, 0.034, 0.042, 0.035, 0.039, 0.047, 0.038, 0.041]
            # for index, num in enumerate(range_list):
            #     if num == 0:
            #         continue
            #     rangey = random.randint(-2, 2)
            #     rangeTime = random.choice(rangeTimeList)
            #     rangeTimeList.remove(rangeTime)
            #     tagx += num
            #     print(distance)
            #     pyautogui.moveTo(tagx, tagy + rangey, duration=rangeTime)
            # sleep(0.5)
            # pyautogui.moveTo(tagx+1, tagy)
            # print("---------------")
            # pyautogui.mouseUp()
            # sleep(1)

            return False
        else:
            return True

    # 提交手机验证
    def commit_phone_code(self):
        tips = self.browser.find_elements(By.CLASS_NAME, "tip-btnbox")
        if len(tips) > 0:
            self.browser.find_element(By.CLASS_NAME, "tip-btnbox").click()

            sleep(1)
            phone_code_id = self.phone_check()

            skShopInfo = sk_shop_info()
            if phone_code_id > 0:
                # 获取到验证码点击提交按钮
                self.browser.find_element(By.CLASS_NAME, "btn-m").click()

                sleep(2)
                # 检测是否有错误信息
                phoneCodeErrors = self.browser.find_elements(By.CLASS_NAME, "input-error")
                if len(phoneCodeErrors) > 0:
                    errorText = self.browser.find_element(By.CLASS_NAME, "input-error").text
                    if len(errorText) > 0:
                        # 从新发送一次
                        # phone_code_id = self.phone_check()
                        # if phone_code_id == 0:
                        #     skShopInfo.update_abnormal_shop_id(shop_id=self.shop[0], msg="未获取到短信验证码")
                        skShopInfo.update_abnormal_shop_id(shop_id=self.shop[0], msg=errorText)
                        return False
                    else:
                        return True
            else:
                skShopInfo.update_abnormal_shop_id(shop_id=self.shop[0], msg="未获取到短信验证码")
                return False
        else:
            return True

    # 手机验证
    def phone_check(self):
        # 发送手机验证码
        self.browser.find_element(By.CLASS_NAME, "dialog-wrapper").find_element(By.CLASS_NAME, "btn-msg").click()

        # 拨打电话
        httpPhone = http_phone()
        httpPhone.send_phone_code(phone=self.shop[29], shop_name=self.shop[1], call_phone=self.shop[32])

        # 当前时间
        timestamp = int(time())
        # 过期时间
        invalid_time = timestamp + PHONE_CODE_INVALID_TIME

        # 保存发送验证码数据
        phone_code_data = sk_shop_phone_code(user_id=self.shop[28], shop_id=self.shop[0], send_time=timestamp,
                                        status=SENDING, code="", submit_time=0, expire_time=invalid_time)

        phoneCode = sk_shop_phone_code()

        phone_code_id = phoneCode.insert_phone_code(phone_code=phone_code_data)
        if phone_code_id <= 0:
            logger.error("店铺{},ID{}获取验证码错误".format(self.shop[1], self.shop[0]))
            return 0

        # 验证码状态
        phone_code_status = False

        while timestamp <= invalid_time and phone_code_status is False:
            timestamp = timestamp + 10
            code = phoneCode.get_phone_code_by_id(id=phone_code_id)
            print(phone_code_id)
            print(code)
            if code[1]:
                phone_code_status = True
                self.browser.find_element(By.CLASS_NAME, "field").send_keys(code[1])
            sleep(10)

        if phone_code_status is True:
            return phone_code_id
        else:
            phoneCode.update_shop_code_status(phone_code_id, INVALID)
            return 0

    # 生成随即数
    def range_ragulation(self, distance):

        # 数组
        number_list = []

        if distance <= 30:
            number_list.append(distance)

        if distance > 30 and distance <= 60:
            if distance <= 40:
                rangeNum = random.randint(25, 30)

            if distance > 40 and distance <= 50:
                rangeNum = random.randint(35, 40)

            if distance > 50:
                rangeNum = random.randint(45, 50)
            number_list.append(rangeNum)
            number_list.append(distance - rangeNum)

        if distance > 60:
            avg = distance//2
            four = distance//4
            eight = distance//8
            rangeNum = random.randint(avg-3, avg)  # 33
            rangeNum1 = random.randint(four-3, four)  # 18
            rangeNum2 = random.randint(eight-4, eight)  # 12
            dis = distance - rangeNum - rangeNum1 - rangeNum2
            if dis < 5:
                rangeNum3 = dis - 1
                rangeNum4 = 1
            else:
                rangeNum3 = random.randint(dis-10, dis-5)
                rangeNum4 = distance - rangeNum - rangeNum1 - rangeNum2 - rangeNum3

            number_list.append(rangeNum)
            number_list.append(rangeNum1)
            number_list.append(rangeNum2)
            number_list.append(rangeNum3)
            number_list.append(rangeNum4)


        return sorted(number_list, reverse=True)

    def get_url_his_data(self, cookie, timestamp):

        dt = datetime.datetime.fromtimestamp(timestamp)
        # 插入数据时间
        insert_time = dt.strftime('%Y-%m-%d %H:%M:%S')
        # 获取数据时间
        date_time = dt.strftime('%Y-%m-%d')

        # 替换特殊字符
        cookie = cookie.replace("\n", "").replace("\\s", "")

        header = {
            "Cookie": cookie
        }

        workUrl = WORK_URL.format(date_time, date_time)
        print(workUrl)
        print(cookie)
        work_data = requests.get(url=workUrl, headers=header, verify=False)
        work_res_data = work_data.json()
        logger.info("工作量 店铺 {}，时间 {}， 数据：{}".format(self.shop[1], date_time, json.dumps(work_res_data)))

        # 数据
        res = []

        if work_res_data["code"] != "success":
            return res

        # 平均数据
        shopReport = shop_report()

        for data in work_res_data["workKpiList"]:
            for account in self.accounts:
                if data["waiter"] == account.shop_account:
                    hisKpi = his_kpi()

                    hisKpi.staff_name = data["waiter"]
                    hisKpi.labor_amount = data["receiveNum"]
                    hisKpi.labor_user_amount = data["receiveNum"]
                    hisKpi.inquirer_amount = data["consultNum"]
                    if "receiveNum30Rate" in data:
                        hisKpi.thirty_sec_response_rate = data["receiveNum30Rate"]
                    else:
                        hisKpi.thirty_sec_response_rate = "-"
                    if data["satisfiedRate"]:
                        satisfiedRate = float(data["satisfiedRate"])
                        hisKpi.satisfaction_rate = satisfiedRate
                        hisKpi.dissatisfaction_rate = 100 - satisfiedRate
                    hisKpi.online_duration = data["serviceTime"]
                    if "responseAvgSpeed" in data:
                        hisKpi.avg_response_duration = data["responseAvgSpeed"]
                    else:
                        hisKpi.avg_response_duration = "-"
                    hisKpi.staff_username = data["waiter"]
                    hisKpi.insert_time = insert_time
                    hisKpi.insert_timestamp = (timestamp * 1000)
                    hisKpi.user_id = self.shop[14]
                    hisKpi.user_name = self.shop[20]
                    hisKpi.shop_id = self.shop[0]
                    hisKpi.shop_name = self.shop[1]
                    hisKpi.user_ids = self.shop[15]
                    hisKpi.dept_id = self.shop[13]
                    hisKpi.dept_ids = self.shop[22]
                    hisKpi.dept_names = self.shop[23]
                    hisKpi.business_manager_ids = self.shop[23]
                    hisKpi.business_manager_names = self.shop[24]
                    hisKpi.base_manager_ids = self.shop[25]
                    hisKpi.base_manager_names = self.shop[26]
                    hisKpi.platform = JINGDONG

                    res.append(hisKpi)

        shopReport.platform = JINGDONG
        shopReport.shop_id = self.shop[0]
        shopReport.insert_timestamp = timestamp * 1000
        shopReport.three_min_response_rate = "-"
        shopReport.inquiry_conversion_rate = "-"
        shopReport.avg_response_duration = work_res_data["AvgDetail"]["responseAvgDurationWithLeave"]
        shopReport.satisfaction_rate = work_res_data["AvgDetail"]["satisfiedRate"]
        shopReport.savaShopReport(shop_report=shopReport)
        return res






